/**
 * Copyright (c) 2006 Amgad S Youssef
 * All Rights Reserved.
 * Licensed under the Eclipse Public License - v 1.0
 * For more information see http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipsejcde.jcbp.wizards.jcapplet.pages;

import java.util.ArrayList;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.ui.wizards.NewClassWizardPage;
import org.eclipsejcde.core.JCDECore;
import org.eclipsejcde.wizards.jcapplet.pages.NewJCAppletExtraFeaturesWizardPage;
import org.eclipsejcde.wizards.jcapplet.pages.NewJCAppletWizardPage;

/**
 * @author Amgad S Youssef
 * 
 */
public class NewJCBPAppletExtraFeaturesWizardPage extends NewJCAppletExtraFeaturesWizardPage {
	public NewJCBPAppletExtraFeaturesWizardPage(NewJCAppletWizardPage newJCAppletWizardPage) {
		super(newJCAppletWizardPage);
	}

	@Override
	public void createSIImplType(IProgressMonitor monitor) throws CoreException, InterruptedException {
		// validations
		if (this.bean == null || !(this.bean.isSupportsSI() && this.bean.isServerApplet())) {
			return;
		}
		if (this.bean.getSiImplName() == null || this.bean.getSiImplName().equals("")) {
			return;
		}
		if (createdSIType == null) {
			createSIType(monitor);
		}

		// extract package name
		String packageName = extractPackageName(this.bean.getSiImplName());
		String siImplName = extractSimpleJavaTypeName(this.bean.getSiImplName());

		// create package
		IPackageFragmentRoot packFragRoot = this.newJCAppletWizardPage.getPackageFragmentRoot();
		IPackageFragment packFrag = packFragRoot.createPackageFragment(packageName, true, monitor);

		// create class
		NewClassWizardPage classUtil = new NewClassWizardPage();
		classUtil.setPackageFragment(packFrag, true);
		classUtil.setSuperClass("sosframework.SIProxy", true);
		classUtil.setTypeName(siImplName, true);
		ArrayList superInterfaceList = new ArrayList();
		superInterfaceList.add(createdSIType.getFullyQualifiedName());
		classUtil.setSuperInterfaces(superInterfaceList, true);
		classUtil.setMethodStubSelection(false, true, true, true);
		classUtil.createType(monitor);
		createdSIImplType = classUtil.getCreatedType();

		// generate code
		if (this.bean.isGenerateSISampleCode()) {
			monitor.setTaskName("generating shareable interface implementer code");
			generateSIImplTypeSampleCode(monitor);
		}
	}

	@Override
	public void generateSIImplTypeSampleCode(IProgressMonitor monitor) throws CoreException {
		IType createdType = this.newJCAppletWizardPage.getCreatedType();
		StringBuffer content = null;
		IMethod[] methods = null;
		IStatus status = null;
		IMethod constructor = null;
		IJavaElement sibling = null;

		// add SIO ID static field
		content = new StringBuffer("");
		content.append("public static final byte SIO_ID = (byte) 0x01;");
		createdSIType.createField(content.toString(), null, true, monitor);

		// removing constructors
		methods = createdSIImplType.getMethods();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i].isConstructor()) {
				methods[i].delete(true, monitor);
			}
		}

		// creating a new contructor
		content = new StringBuffer();
		content.append("public " + createdSIImplType.getElementName() + "(AuthorizationManager authorizationManager) {");
		content.append("super(authorizationManager, SIO_ID);");
		content.append("}");
		methods = createdSIImplType.getMethods();
		sibling = null;
		if (methods.length > 0) {
			sibling = methods[0];
		}
		status = JCDECore.formatMethodCode(content.toString(), createdSIImplType.getJavaProject());
		if (status.getSeverity() == IStatus.OK) {
			createdSIImplType.createMethod(status.getMessage(), sibling, true, monitor);
		} else {
			createdSIImplType.createMethod(content.toString(), sibling, true, monitor);
		}

		// adding sampleMethod() method
		content = new StringBuffer("");
		IMethod sampleMethod = createdSIImplType.getMethod("sampleMethod", new String[] {});
		if (sampleMethod != null && sampleMethod.exists()) {
			content = new StringBuffer(sampleMethod.getSource());
			content.insert(content.indexOf("{") + 1, "if (!isAuthorized()) {\nreturn -1;\n}");
			sampleMethod.delete(true, monitor);
		} else {
			content.append("public short sampleMethod() {\n");
			content.append("if (!isAuthorized()) {\n");
			content.append("return -1;\n");
			content.append("}\n");
			content.append("\treturn 0;\n");
			content.append("}");
		}
		status = JCDECore.formatMethodCode(content.toString(), createdSIImplType.getJavaProject());
		if (status.getSeverity() == IStatus.OK) {
			createdSIImplType.createMethod(status.getMessage(), null, true, monitor);
		} else {
			createdSIImplType.createMethod(content.toString(), null, true, monitor);
		}

		// generating Applet sample code

		// adding imports
		createdType.getCompilationUnit().createImport("javacard.framework.JCSystem", null, monitor);
		createdType.getCompilationUnit().createImport("sosframework.SecureSIFree", null, monitor);
		createdType.getCompilationUnit().createImport(createdSIType.getPackageFragment().getElementName() + "." + createdSIType.getElementName(), null, monitor);
		createdType.getCompilationUnit().createImport(createdSIImplType.getPackageFragment().getElementName() + "." + createdSIImplType.getElementName(), null, monitor);

		// create internal class
		content = new StringBuffer("");
		content.append("private class SecureSIFreeImpl implements SecureSIFree {");
		content.append("public void register(byte sioID) {");
		content.append("getAuthorizationManager().register(sioID, JCSystem.getPreviousContextAID());");
		content.append("}");
		content.append("}");
		status = JCDECore.formatClassCode(content.toString(), createdType.getJavaProject());
		if (status.getSeverity() == IStatus.OK) {
			createdType.createType(status.getMessage(), null, true, monitor);
		} else {
			createdType.createType(content.toString(), null, true, monitor);
		}

		// updating constructor
		constructor = createdType.getMethod(createdType.getElementName(), new String[] {});
		if (constructor != null && constructor.exists()) {
			content = new StringBuffer(constructor.getSource());
			content.replace(content.indexOf("super"), content.indexOf(";", content.indexOf("super")) + 1, "super((byte) 1, (byte) 1, (byte) 10, CLEAR_ON_RESET);");
			content.insert(content.lastIndexOf("}"), "getAuthorizationManager().provideSIO(" + createdSIType.getElementName() + ".SIO_ID, new " + createdSIImplType.getElementName()
					+ "(getAuthorizationManager()), new SecureSIFreeImpl());\n");
			constructor.delete(true, monitor);
		} else {
			content = new StringBuffer();
			content.append("private " + createdType.getElementName() + "() {");
			content.append("super((byte) 1, (byte) 1, (byte) 10, CLEAR_ON_RESET);");
			content.append("getAuthorizationManager().provideSIO(" + createdSIType.getElementName() + ".SIO_ID, new " + createdSIImplType.getElementName()
					+ "(getAuthorizationManager()), new SecureSIFreeImpl());\n");
			content.append("}");
		}
		methods = createdType.getMethods();
		sibling = null;
		if (methods.length > 0) {
			sibling = methods[0];
		}
		status = JCDECore.formatMethodCode(content.toString(), createdType.getJavaProject());
		if (status.getSeverity() == IStatus.OK) {
			createdType.createMethod(status.getMessage(), sibling, true, monitor);
		} else {
			createdType.createMethod(content.toString(), sibling, true, monitor);
		}
	}

}
